//  Inside Microsoft Exchange 2007 Web Services 
//  Chapter 16
//
//  Copyright (c) 2007 David Sterling, Ben Spain, Mark Taylor, Huw Upshall, Michael Mainer.  
//  All rights reserved.
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using ProxyHelpers.EWS;
using System.Diagnostics;

namespace SyncFolderItemsWithChange
{
    class Program
    {
        static void Main(string[] args)
        {
            ExchangeServiceBinding binding = new ExchangeServiceBinding();
            binding.Url = "https://yourServer/ews/Exchange.asmx";
            binding.Credentials = new NetworkCredential("username", "password", "domain");

            string syncState = null;
            List<ItemType> createdItems;
            List<ItemType> updatedItems;
            List<ItemIdType> deletedItems;

            SyncFolderItemsWithChange(
                        binding,
                        new DistinguishedFolderIdType(DistinguishedFolderIdNameType.inbox),
                        ref syncState,
                        new ItemResponseShapeType(DefaultShapeNamesType.Default),
                        out createdItems,
                        out updatedItems,
                        out deletedItems);
        }

        /// <summary>
        /// SyncFolderItems and separate the create, update and delete changes (Listing 16-33)
        /// </summary>
        /// <param name="binding">Binding to use for call</param>
        /// <param name="syncFolderId">Folder to sync from</param>
        /// <param name="syncState">REF sync state to use (and update outbound)</param>
        /// <param name="responseShape">Response shape</param>
        /// <param name="createdItems">OUT list of create items. Could be null.</param>
        /// <param name="updatedItems">OUT list of updated items. Could be null.</param>
        /// <param name="deletedItems">OUT list of deleted items. Could be null.</param>
        /// 
        public static void SyncFolderItemsWithChange(
                                      ExchangeServiceBinding binding,
                                      BaseFolderIdType syncFolderId,
                                      ref string syncState,
                                      ItemResponseShapeType responseShape,
                                      out List<ItemType> createdItems,
                                      out List<ItemType> updatedItems,
                                      out List<ItemIdType> deletedItems)
        {
            SyncFolderItemsType request = new SyncFolderItemsType();
            request.ItemShape = responseShape;
            request.MaxChangesReturned = 512;
            request.SyncFolderId = new TargetFolderIdType();
            request.SyncFolderId.Item = syncFolderId;

            request.SyncState = syncState;
            SyncFolderItemsResponseType response = binding.SyncFolderItems(request);
            SyncFolderItemsResponseMessageType responseMessage =
                   response.ResponseMessages.Items[0] as SyncFolderItemsResponseMessageType;

            if (responseMessage.ResponseCode != ResponseCodeType.NoError)
            {
                throw new Exception("SyncFolderItems failed with response code: " +
                             responseMessage.ResponseCode.ToString());
            }

            createdItems = null;
            updatedItems = null;
            deletedItems = null;

            if (responseMessage.Changes.Items == null)
            {
                // No changes!
                //
                return;
            }

            for (int index = 0; index < responseMessage.Changes.Items.Length; index++)
            {
                switch (responseMessage.Changes.ItemsElementName[index])
                {
                    case ItemsChoiceType2.Create:
                        if (createdItems == null)
                        {
                            createdItems = new List<ItemType>();
                        }
                        SyncFolderItemsCreateOrUpdateType create =
                           responseMessage.Changes.Items[index] as SyncFolderItemsCreateOrUpdateType;
                        createdItems.Add(create.Item);
                        break;

                    case ItemsChoiceType2.Update:
                        if (updatedItems == null)
                        {
                            updatedItems = new List<ItemType>();
                        }
                        SyncFolderItemsCreateOrUpdateType update =
                           responseMessage.Changes.Items[index] as SyncFolderItemsCreateOrUpdateType;
                        updatedItems.Add(update.Item);
                        break;

                    case ItemsChoiceType2.Delete:
                        if (deletedItems == null)
                        {
                            deletedItems = new List<ItemIdType>();
                        }
                        SyncFolderItemsDeleteType delete =
                             responseMessage.Changes.Items[index] as SyncFolderItemsDeleteType;
                        deletedItems.Add(delete.ItemId);
                        break;
                }
            }
            syncState = responseMessage.SyncState;
        }

    }
}
